package naga.x.net.proxy;

import java.nio.charset.Charset;

import naga.x.net.Packet;

import org.apache.mina.core.buffer.IoBuffer;

/**
 * 与代理服务器通信的网络包<br/>
 * <pre>
 *   HEAD          (2 bytes) 头部
 *   DATA LENGTH   (1 int)   数据长度(以下所有字段长度总和)
 *   OPCODE        (1 short) 协议号
 *   SESSION ID    (1 int)   客户端与代理服务器连接的会话id
 *   SERIAL        (1 int)   序列号
 *   PACKET TYPE   (1 byte)  数据包类型,pomelo中表示package type
 *   DATA          (n bytes) 具体数据
 * </pre>
 * @author YangLi
 *
 */
public class ProxyPacket extends Packet {

	public static final byte[] HEAD = new byte[] { 'P', 'A' };
	public static final Charset UTF8 = Charset.forName("utf-8");
	private static final IoBuffer EMPTY = IoBuffer.allocate(0);
	
	protected IoBuffer data;
	protected int sessionId; // 客户端与代理服务器连接的会话id
	protected int serial;
	protected byte type;
	
	public ProxyPacket(short opCode) {
		this(opCode, 128, -1, -1, (byte) -1);
	}
	
	public ProxyPacket(short opCode, int capacity, int sessionId, int serial, int type) {
		this(opCode, IoBuffer.allocate(capacity).setAutoExpand(true), sessionId, serial, type);
	}
	
	public ProxyPacket(short opCode, IoBuffer data, int sessionId, int serial, int type) {
		this.opCode = opCode;
		this.data = data != null ? data : EMPTY;
		this.sessionId = sessionId;
		this.serial = serial;
		this.type = (byte) type;
	}
	
	public int getSessionId() {
		return sessionId;
	}

	public void setSessionId(int sessionId) {
		this.sessionId = sessionId;
	}

	public int getSerial() {
		return serial;
	}

	public void setSerial(int serial) {
		this.serial = serial;
	}

	public byte getType() {
		return type;
	}

	public void setType(byte type) {
		this.type = type;
	}

	public byte get() {
		return data.get();
	}
	
	public void put(int b) {
		data.put((byte) b);
	}
	
	public void put(byte b) {
		data.put(b);
	}
	
	public int getUnsignedByte() {
		return data.getUnsigned();
	}
	
	public void putUnsignedByte(byte b) {
		data.putUnsigned(b);
	}
	
	public byte[] get(byte[] b) {
		data.get(b);
		return b;
	}
//	public byte[] getBytes() {
//		int len = data.getInt();
//		byte[] b = new byte[len];
//		data.get(b);
//		return b;
//	}
	
	public void put(byte[] b) {
//		data.putInt(b.length);
		data.put(b);
	}
	
	public void put(byte[] b, int off, int len) {
//		data.putInt(len);
		data.put(b, off, len);
	}
	
	public short getShort() {
		return data.getShort();
	}
	
	public void putShort(short val) {
		data.putShort(val);
	}
	
	public void putShort(int val) {
		data.putShort((short) val);
	}
	
	public int getUnsignedShort() {
		return data.getUnsignedShort();
	}
	
	public void putUnsignedShort(int val) {
		data.putUnsignedShort(val);
	}
	
	public int getInt() {
		return data.getInt();
	}
	
	public void putInt(int val) {
		data.putInt(val);
	}
	
	public long getLong() {
		return data.getLong();
	}
	
	public void putLong(long val) {
		data.putLong(val);
	}
	
	public String getUTF() {
		int len = data.getShort();
		byte[] b = new byte[len];
		data.get(b);
		return new String(b, UTF8);
	}
	
	public void putUTF(String val) {
		byte[] b = val.getBytes(UTF8);
		int len = b.length;
		if (len > Short.MAX_VALUE) {
			throw new IllegalArgumentException("put string too long.");
		}
		data.putShort((short) len);
		data.put(b);
	}

	public IoBuffer getData() {
		return data;
	}
	
	public byte[] getDataAsByteArray() {
		if (data.position() == 0 && data.limit() == data.capacity()) {
			return data.array();
		}
		byte[] b = new byte[data.remaining()];
		data.get(b);
		return b;
	}

}
